package com.hmdp.service.impl;

import com.hmdp.dto.Result;
import com.hmdp.entity.SeckillVoucher;
import com.hmdp.entity.VoucherOrder;
import com.hmdp.mapper.SeckillVoucherMapper;
import com.hmdp.service.ISeckillVoucherService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.service.IVoucherOrderService;
import com.hmdp.utils.RedisIdWorker;
import com.hmdp.utils.SimpleRedisLock;
import com.hmdp.utils.UserHolder;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.hmdp.utils.RedisConstants.SECKILL_ORDER_KEY;

/**
 * <p>
 * 秒杀优惠券表，与优惠券是一对一关系 服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2022-01-04
 */
@Service
public class SeckillVoucherServiceImpl extends ServiceImpl<SeckillVoucherMapper, SeckillVoucher> implements ISeckillVoucherService {

    private static DefaultRedisScript<Long> SECKILL_SCRIPT ;
    static {
        SECKILL_SCRIPT = new DefaultRedisScript<>();
        SECKILL_SCRIPT.setLocation(new ClassPathResource("seckill.lua"));
        SECKILL_SCRIPT.setResultType(Long.class);
    }
    @Autowired
    private IVoucherOrderService voucherOrderService;

    @Autowired
    private RedisIdWorker redisIdWorker;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Resource(name = "redissonClient")
    private RedissonClient redissonClient;

    @Override
    public Result seckillVoucher(Long voucherId) {
        Long userId = UserHolder.getUser().getId();
        Long orderId = redisIdWorker.nextId(SECKILL_ORDER_KEY);
        // 调用lua脚本
        // 1.执行lua脚本
        Long result = stringRedisTemplate.execute(
                SECKILL_SCRIPT,
                Collections.emptyList(),
                voucherId.toString(), userId.toString(), String.valueOf(orderId)
        );
        // 返回值不等于0，不可以下单
        if (!Objects.equals(result, 0)){
            return Objects.equals(result, 1) ? Result.fail("库存不足无法下单") : Result.fail("用户已下单不可重复下单");
        }

        // TODO 保存阻塞队列
        // 返回值为0，可以下单
        return Result.ok(orderId);
    }

    @Override
    public Result createNewOrder(Long voucherId) {
        return null;
    }

    /**
     * 用户秒杀
     * @param voucherId
     * @return
     */
//    @Override
//    public Result seckillVoucher(Long voucherId) {
//        // 查询优惠券信息
//        SeckillVoucher seckillVoucher = getById(voucherId);
//
//        // 如果已过期则返回异常信息
//        LocalDateTime now = LocalDateTime.now();
//        if (now.isBefore(seckillVoucher.getBeginTime())){
//            return Result.fail("秒杀活动未开启");
//        }
//
//        if (now.isAfter(seckillVoucher.getEndTime())){
//            return Result.fail("秒杀活动已结束");
//        }
//
//        // 判断库存是否充足
//        int stock = seckillVoucher.getStock();
//        if (stock <= 0){
//            // 如果不充足则返回异常信息
//            return Result.fail("库存不足");
//        }
//
//        // 判断当前用户是否已下单
//        Long userId = UserHolder.getUser().getId();
//        // 单体环境下可以使用synchronized实现
////        synchronized (userId.toString().intern()){
////            ISeckillVoucherService proxy = (ISeckillVoucherService) AopContext.currentProxy();
////            return proxy.createNewOrder(voucherId);
////        }
//
//        // 分布式环境下必须使用分布式锁，这里使用redis实现分布式锁
//        String key = "order:" + userId + ":";
////        SimpleRedisLock lock = new SimpleRedisLock(key, stringRedisTemplate);
//        RLock lock = redissonClient.getLock(key);
//        boolean isLock = lock.tryLock();
//        // 如果获取锁失败则返回异常信息
//        if (!isLock){
//            return Result.fail("一个用户只能下单一次");
//        }
//
//        try{
//            ISeckillVoucherService proxy = (ISeckillVoucherService) AopContext.currentProxy();
//            Result result = proxy.createNewOrder(voucherId);
//            return result;
//        }finally {
//            lock.unlock();
//        }
//
//    }
//
//    @Transactional
//    public Result createNewOrder(Long voucherId){
//        Long userId = UserHolder.getUser().getId();
//        int count = voucherOrderService.query().eq("user_id", userId).eq("voucher_id", voucherId).count();
//        if (count > 0){
//            return Result.fail("一个用户只能下单一次");
//        }
//
//        // 充足则扣减库存,为了解决库存的线程安全问题，所以扣减前先判断当前库存量是否大于0
//        boolean success = update().setSql("stock = stock - 1").eq("voucher_id", voucherId).gt("stock", 0).update();
//
//        if (!success){
//            // 如果扣减失败则返回异常信息
//            return Result.fail("库存不足");
//        }
//        // 创建订单
//        VoucherOrder voucherOrder = new VoucherOrder();
//        long orderId = redisIdWorker.nextId("order");
//        voucherOrder.setId(orderId);
//        voucherOrder.setUserId(UserHolder.getUser().getId());
//        voucherOrder.setVoucherId(voucherId);
//        voucherOrderService.save(voucherOrder);
//
//        return Result.ok(orderId);
//    }
}
